﻿using System;
using System.Collections.Generic;
using __ts.Core.Api;
using log4net;

/*
 *  author: able
 *  @2012/2/21 12:26:14
 * 
 */
namespace __ts.Core.Service
{
    /// <summary>
    /// 
    /// </summary>
    public abstract class AbstractIoService : IoService
    {
        /** A logger for this class */
        static ILog LOG = LogManager.GetLogger(typeof(AbstractIoService));

        /** The service state */
        private ServiceState state;

        /** The service mode : secured or not */
        private ServiceMode mode;

        /** The SSLContext instance */
        //private SSLContext sslContext;

        private IDictionary<string, IoSession> managedSessions = null;//new ConcurrentHashMap<Long, IoSession>();

        /**
         * The handler, the interface with the application part.
         */
        private IoHandler handler;

        /**
         * Placeholder for storing all the listeners added
         */
        private List<IoServiceListener> listeners = null;//new CopyOnWriteArrayList<IoServiceListener>();

        /**
         * The Service states
         */
        protected enum ServiceState
        {
            /** Initial state */
            NONE,
            /** The service has been created */
            CREATED,
            /** The service is started */
            ACTIVE,
            /** The service has been suspended */
            SUSPENDED,
            /** The service is being stopped */
            DISPOSING,
            /** The service is stopped */
            DISPOSED
        }

        /**
         * The Service secured mode
         */
        protected enum ServiceMode
        {
            /** SSL/TLS activated */
            SECURED,
            /** SSL/TLS not activated */
            NOT_SECURED
        }

        /**
         * Create an AbstractIoService
         */
        protected AbstractIoService()
        {
            state = ServiceState.NONE;
            mode = ServiceMode.NOT_SECURED;
        }

        public IDictionary<string, IoSession> getManagedSessions()
        {
            return managedSessions;
        }

        /**
         * 
         * {@inheritDoc}
         */
        public void addListener(IoServiceListener listener)
        {
            if (listener != null)
            {
                listeners.Add(listener);
                return;
            }

            LOG.Warn("Trying to add Null Listener");
        }

        /**
         * 
         * {@inheritDoc}
         */
        public void removeListener(IoServiceListener listener)
        {
            if (listener != null)
            {
                listeners.Remove(listener);
            }
        }

        /**
         * {@inheritDoc}
         */
        public IoHandler getHandler()
        {
            return handler;
        }

        /**
         * {@inheritDoc}
         */
        public void setHandler(IoHandler handler)
        {
            if (handler == null)
            {
                throw new ArgumentNullException("handler cannot be null");
            }

            // TODO: check the service state, we should not be able to set the handler
            // if the service is already started
            /*
             * if (isActive()) { throw new IllegalStateException( "handler cannot be set while the service is active."); }
             */

            this.handler = handler;
        }

        /**
         * @return true if the IoService is active
         */
        public bool isActive()
        {
            return state == ServiceState.ACTIVE;
        }

        /**
         * @return true if the IoService is being disposed
         */
        public bool isDisposing()
        {
            return state == ServiceState.DISPOSING;
        }

        /**
         * @return true if the IoService is disposed
         */
        public bool isDisposed()
        {
            return state == ServiceState.DISPOSED;
        }

        /**
         * @return true if the IoService is suspended
         */
        public bool isSuspended()
        {
            return state == ServiceState.SUSPENDED;
        }

        /**
         * @return true if the IoService is created
         */
        public bool isCreated()
        {
            return state == ServiceState.CREATED;
        }

        /**
         * Sets the IoService state to CREATED.
         */
        protected void setCreated()
        {
            state = ServiceState.CREATED;
        }

        /**
         * Sets the IoService state to ACTIVE.
         */
        protected void setActive()
        {
            state = ServiceState.ACTIVE;
        }

        /**
         * Sets the IoService state to DISPOSED.
         */
        protected void setDisposed()
        {
            state = ServiceState.DISPOSED;
        }

        /**
         * Sets the IoService state to DISPOSING.
         */
        protected void setDisposing()
        {
            state = ServiceState.DISPOSING;
        }

        /**
         * Sets the IoService state to SUSPENDED.
         */
        protected void setSuspended()
        {
            state = ServiceState.SUSPENDED;
        }

        /**
         * Initialize the IoService state
         */
        protected void initState()
        {
            state = ServiceState.NONE;
        }

        /**
         * Inform all current the listeners of the service activation.
         */
        protected void fireServiceActivated()
        {
            foreach (IoServiceListener listener in listeners)
            {
                listener.serviceActivated(this);
            }
        }

        /**
         * Inform all current the listeners of the service desactivation.
         */
        protected void fireServiceInactivated()
        {
            foreach (IoServiceListener listener in listeners)
            {
                listener.serviceInactivated(this);
            }
        }

        public void fireSessionCreated(IoSession session)
        {
            foreach (IoServiceListener listener in listeners)
            {
                listener.sessionCreated(session);
            }
        }

        public void fireSessionDestroyed(IoSession session)
        {
            foreach (IoServiceListener listener in listeners)
            {
                listener.sessionDestroyed(session);
            }
        }

        private IoFilter[] filters;

        /**
         * {@inheritDoc}
         */
        public IoFilter[] getFilters()
        {
            return filters;
        }

        /**
         * {@inheritDoc}
         */
        public void setFilters(params IoFilter[] filters)
        {
            this.filters = filters;
        }

        /**
         * Tells if the service provide some encryption (SSL/TLS)
         * @return <code>true</code> if the service is secured
         */
        public bool isSecured()
        {
            return mode == ServiceMode.SECURED;
        }

        /**
         * {@inheritDoc}
         */
        public void setSecured(bool secured)
        {
            if (secured)
            {
                mode = ServiceMode.SECURED;
            }
            else
            {
                mode = ServiceMode.NOT_SECURED;
            }
        }

        /**
         * {@inheritDoc}
         */
        //public void setSslContext(SSLContext sslContext) {
        //    this.sslContext = sslContext;
        //    mode = ServiceMode.SECURED;
        //}

        /**
         * {@inheritDoc}
         */
        //public SSLContext getSslContext() {
        //    return sslContext;
        //}


        public abstract IoSessionConfig getSessionConfig();
    }
}